#include "unary_parser.h"

using namespace std;
using namespace eg;

//==================================================================================================
//                            Specific parsers implementation
//==================================================================================================

// unary_parser: left recursion check
bool unary_parser::left_recursive(parser * from) {
	cout << "left...\n";
	return argument->left_recursive(from);
}

// And predicate: &E
bool and_parser::parse(bool gen_ast) {
	int old_size_of_stack = the_context->s.size();
	pos_type pos = the_context->input.tellg();
	//cout << "trying parsing " << to_string() << " ..." << endl;
	//the_context->error_rule_stack.top()->error_parsers_stack.push(this);
	bool r = argument->parse(false); // do not create a syntax tree
	the_context->input.seekg(pos); // rewind
	return (r) ? true : reject(pos, the_context->s.size() - old_size_of_stack);
}

// Not predicate: !E
bool not_parser::parse(bool gen_ast) {
	int old_size_of_stack = the_context->s.size();
	pos_type pos = the_context->input.tellg();
	//the_context->error_rule_stack.top()->error_parsers_stack.push(this);
	//cout << "trying parsing " << to_string() << " ..." << endl;
	bool r = argument->parse(false); // do not create a syntax tree
	the_context->input.seekg(pos);
	return (!r) ? true : reject(pos, the_context->s.size() - old_size_of_stack);
}

// Zero or more: E*
bool zero_or_more_parser::parse(bool gen_ast) {

	//cout << "trying parsing " << to_string() << " ..." << endl;
	//the_context->error_rule_stack.top()->error_parsers_stack.push(this);
	if (the_context->skip_parser)
		the_context->skip_parser->parse();
	while (argument->parse(gen_ast&& !the_context->brake_error_parser))
		;
	the_context->brake_error_parser = 0; //Initialize  brake_error_parser
	return true;
}

// One or more: E+
bool one_or_more_parser::parse(bool gen_ast) {

	int old_size_of_stack = the_context->s.size();
	pos_type pos = the_context->input.tellg();
	//the_context->error_rule_stack.top()->error_parsers_stack.push(this);

	//cout << "trying parsing " << to_string() << " ..." << endl;
	if (!argument->parse())
		return reject(pos, the_context->s.size() - old_size_of_stack);
	if (the_context->skip_parser)
		the_context->skip_parser->parse();
	while (argument->parse(gen_ast) && !the_context->brake_error_parser)
		;
	the_context->brake_error_parser = 0; //Initialize  brake_error_parser
	return true;
}

// Zero or one: E?
bool zero_or_one_parser::parse(bool gen_ast) {

	//cout << "trying parsing " << to_string() << " ..." << endl;
	//the_context->error_rule_stack.top()->error_parsers_stack.push(this);
	argument->parse(gen_ast);
	return true;
}

//==================================== rule implementation =========================================
bool rule::parse(bool gen_ast) {

	pos_type pos = the_context->input.tellg();
	int old_size_of_stack = the_context->s.size();
	if (this->r_name != "error" and this->r_name != "blanks" )
	the_context->error_rule_stack.push(this);
	if (argument->parse(gen_ast)) {
		string node_desc;
		if (gen_ast && (argument->parser_name() != "error") && (argument->parser_name() != "eof") ) {
			return accept(r_name, pos, the_context->s.size()
					- old_size_of_stack);
		}
		return 1;
	} else
		return reject(pos, the_context->s.size() - old_size_of_stack);
	return 0;
}
